package com.ccp.dev.workflow.service.bpm.cmd;

import com.ccp.dev.core.util.AppUtil;
import com.ccp.dev.workflow.dao.BpmProStatusDao;
import com.ccp.dev.workflow.event.CallActivityBackEvent;
import com.ccp.dev.workflow.model.TaskOpinion;
import com.ccp.dev.workflow.model.bpm.ProcessCmd;
import com.ccp.dev.workflow.service.BpmService;
import com.ccp.dev.workflow.service.bpm.thread.TaskThreadService;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * ClassDescribe:
 * 子流程驳回命令。
 * <pre>
 * 1.传入子流程的任务ID。
 * 2.查询父实例是否存在，如果不存在则直接返回。
 * 3.查询到父实例后，取得他的父实例，直到他的scope为true为止。
 * </pre>
 * @author :wangcheng
 * Date: 2019-11-13
 */
public class CallActivityRejectCmd implements Command<Boolean> {

    private String taskId = "";
    private String targetNode = "";

    public CallActivityRejectCmd() {
    }

    public CallActivityRejectCmd(String taskId) {
        this.taskId = taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public void setTargetNode(String targetNode) {
        this.targetNode = targetNode;
    }

    @Override
    public Boolean execute(CommandContext commandContext) {
        BpmService bpmService = AppUtil.getBean(BpmService.class);
        BpmProStatusDao bpmProStatusDao = AppUtil.getBean(BpmProStatusDao.class);
        ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
        TaskEntity task = CommandContextUtil.getTaskService().getTask(taskId);
        String executionId = task.getProcessInstanceId();
        ExecutionEntity execution= executionEntityManager.findById(executionId);
        ExecutionEntity superExecution = execution.getSuperExecution();
        String callActivityId = superExecution.getActivityId();
        if (superExecution == null) {
            return false;
        }

        while (!superExecution.isScope()) {
            superExecution = superExecution.getParent();
        }

        List<TaskEntity> taskList = new ArrayList<>();

        //如果是顶级数据实例
        //如果是活动的那说明这个实例为单实例的子流程
        //如果是非活动的说明这个实例为多实例子流程
        // 单实例
        if (superExecution.isActive()) {
            taskList.add(task);
        }else{
            //多实例
            List<ExecutionEntity> executionList = (List<ExecutionEntity>) superExecution.getExecutions();
            for (ExecutionEntity tmp : executionList) {
                ExecutionEntity subExecution = executionEntityManager.findSubProcessInstanceBySuperExecutionId(tmp.getId());
                taskList.addAll(subExecution.getTasks());
            }
        }

        // 定义事件
        CallActivityBackEvent event = new CallActivityBackEvent(taskList);
        event.setCurTaskId(taskId);
        // 发布事件
        AppUtil.publishEvent(event);

        RuntimeService runtimeService = CommandContextUtil.getProcessEngineConfiguration().getRuntimeService();
        runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(executionId)
                .moveActivityIdToParentActivityId(task.getTaskDefinitionKey(), targetNode)
                .changeState();

        // 更新外部子流程节点状态
        Map<String, Object> params = new HashMap<>(3);
        params.put("procInstId", superExecution.getProcessInstanceId());
        params.put("nodeId", callActivityId);
        params.put("status", TaskOpinion.STATUS_REJECT);
        bpmProStatusDao.updStatus(params);

        bpmService.updateAssigneeInfo(task);
        return true;
    }
}
